package org.ofbiz.sys;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;

import javax.imageio.ImageIO;

import org.apache.commons.lang.RandomStringUtils;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityUtil;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.ServiceUtil;

import javolution.util.FastMap;
import sun.misc.BASE64Encoder;

public class SysServices {
    public static String module = SysServices.class.getName();
    public static final String resource = "SysServerUiLabels";

    public static final String OFBIZ_HOME = System.getProperty("ofbiz.home");

    /**
     * 上传
     * 
     * @param dctx
     * @param context
     * @return
     */
    public static Map<String, Object> uploadedFile(DispatchContext dctx, Map<String, ? extends Object> context) {
	Map<String, Object> result = ServiceUtil.returnSuccess();
	Locale locale = (Locale) context.get("locale");
	String dependId = (String) context.get("dependId");
	String imageFolder = (String) context.get("imageFolder");
	try {
	    ByteBuffer imageDataBytes = (ByteBuffer) context.get("uploadedFile");
	    String _uploadedFile_fileName = (String) context.get("_uploadedFile_fileName");
	    if (UtilValidate.isNotEmpty(imageDataBytes) && UtilValidate.isNotEmpty(_uploadedFile_fileName)) {
		_uploadedFile_fileName = _uploadedFile_fileName.replace("}", "");
		_uploadedFile_fileName = _uploadedFile_fileName.replace("{", "");
		String extendName = _uploadedFile_fileName.substring(_uploadedFile_fileName.lastIndexOf("."));
		String uuid = UtilUUID.uuidTomini();
		String imagePath = uuid + extendName.toLowerCase();
		String prefixPath = "";
		if (dependId.length() > 4) {
		    prefixPath = dependId.substring(0, dependId.length() - 4);
		} else {
		    prefixPath = dependId;
		}
		createFile(prefixPath, imagePath, imageDataBytes, imageFolder);

		if (UtilValidate.isEmpty(imageFolder)) {
		    imageFolder = "/hot-deploy/sys/webapp/sys/images/upload/";
		}
		Map<String, Object> async_context = FastMap.newInstance();
		async_context.put("imagePath", (prefixPath + "/" + imagePath));
		async_context.put("path", OFBIZ_HOME + imageFolder);
		Map<String, Object> resMap = dctx.getDispatcher().runSync("imageClipRunnerByRules", async_context);
		result.put("compressImagePath", resMap.get("newImagePath"));
		result.put("compressImageName", imagePath);
//                result.put("imagePath", resMap.get("newImagePath")); 
//                result.put("imageName", imagePath);
		result.put("imagePath", prefixPath + "/" + imagePath);
		result.put("imageName", imagePath);
	    }
	} catch (IOException e) {
	    Debug.logError(e, e.getMessage(), module);
	    return ServiceUtil.returnError(
		    UtilProperties.getMessage(resource, "upload.image.error", new Object[] { e.getMessage() }, locale));
	} catch (GenericServiceException e) {
	    Debug.logError(e, e.getMessage(), module);
	    return ServiceUtil.returnError(
		    UtilProperties.getMessage(resource, "upload.image.error", new Object[] { e.getMessage() }, locale));
	}
	return result;
    }

    /**
     * 图片压缩
     * 
     * @param ctx
     * @param context
     * @return
     */
    public static Map<String, Object> imageClipRunnerByRules(DispatchContext ctx,
	    Map<String, ? extends Object> context) {
	Map<String, Object> result = ServiceUtil.returnSuccess();
	Locale locale = (Locale) context.get("locale");
	String imagePath = (String) context.get("imagePath");
	String path = (String) context.get("path");
	try {
	    String inFilePath = path + imagePath;
	    String fileType = imagePath.substring(imagePath.lastIndexOf('.'));
	    String fileName = imagePath.substring(0, imagePath.lastIndexOf('.'));
	    File newFile = new File(path + fileName + "_compress" + fileType);
	    String srcImgPath = newFile.getAbsoluteFile().toString();
	    String subfix = "jpg";
	    subfix = srcImgPath.substring(srcImgPath.lastIndexOf(".") + 1, srcImgPath.length());

	    if (!subfix.equals("jpg") && !subfix.equals("jpeg") && !subfix.equals("bmp") && !subfix.equals("png")) {
		return result;
	    }

	    File imageFile = new File(inFilePath);
	    Image srcFile = ImageIO.read(imageFile);
	    int w = srcFile.getWidth(null);
	    int h = srcFile.getHeight(null);
	    int width = 720;
	    int height = 0;
	    double bili;
	    if (w > width) {
		bili = width / (double) w;
		height = (int) (h * bili);
	    } else {
		width = w;
		height = h;
	    }

	    BufferedImage buffImg = null;
	    if (subfix.equals("png")) {
		buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
	    } else if (subfix.equals("jpg") || subfix.equals("jpeg") || subfix.equals("bmp")) {
		buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	    }
	    Graphics2D graphics = buffImg.createGraphics();
	    graphics.setBackground(new Color(255, 255, 255));
	    graphics.setColor(new Color(255, 255, 255));
	    graphics.fillRect(0, 0, width, height);
	    graphics.drawImage(srcFile.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
	    ImageIO.write(buffImg, subfix, new File(srcImgPath));
	    result.put("newImagePath", fileName + "_compress" + fileType);

	} catch (IOException e) {
	    Debug.logError(e, e.getMessage(), module);
	    return ServiceUtil.returnError(UtilProperties.getMessage(resource, "upload.image.imageClipRunnerByRules",
		    new Object[] { e.getMessage() }, locale));
	}
	return result;
    }

    public static void createFile(String prefixPath, String filePath, ByteBuffer imageDataBytes, String newImageFolder)
	    throws IOException {
	byte[] imageBytes = imageDataBytes.array();
	String imageFolder = "";
	if (UtilValidate.isNotEmpty(newImageFolder)) {
	    imageFolder = newImageFolder;
	} else {
	    imageFolder = "/hot-deploy/sys/webapp/sys/images/upload/";
	}
	String fullFilePath = OFBIZ_HOME + imageFolder + prefixPath;
	File saveFilePath = new File(fullFilePath);
	if (!saveFilePath.exists()) {
	    boolean m = saveFilePath.mkdirs();
	}
	String path = fullFilePath + "/" + filePath;
	FileOutputStream fos = new FileOutputStream(path);
	fos.write(imageBytes);
	fos.close();
    }

    public static Map<String, Object> getSecurityPerms(DispatchContext dctx, Map<String, ? extends Object> context) {
	Locale locale = (Locale) context.get("locale");
	Map<String, Object> result = ServiceUtil.returnSuccess();
	Delegator delegator = dctx.getDelegator();
	// Security security = dctx.getSecurity();
	List<GenericValue> permsList = new ArrayList<GenericValue>();
	String perms = "";
	String userLoginId = (String) context.get("userLoginId");
	if ("admin".equals(userLoginId) || "bizadmin".equals(userLoginId) || "ltdadmin".equals(userLoginId)) {
	    result.put("permsList", permsList);
	    result.put("perms", "*");

	    return result;
	}
	if (UtilValidate.isNotEmpty(userLoginId)) {
	    try {
		List<GenericValue> groupList = delegator.findByAnd("UserLoginSecurityGroup",
			UtilMisc.toMap("userLoginId", userLoginId), null, true);
		groupList = EntityUtil.filterByDate(groupList, true);
		for (GenericValue securityGroup : groupList) {
		    String groupId = securityGroup.getString("groupId");
		    List<GenericValue> permissionList = delegator.findByAnd("SecurityGroupAndPermission",
			    UtilMisc.toMap("groupId", groupId), null, true);
		    permsList.addAll(permissionList);
		}
		for (GenericValue sv : permsList) {
		    String locationPath = sv.getString("locationPath");
		    if (UtilValidate.isNotEmpty(locationPath)) {
			perms += locationPath + ",";
		    }
		}
	    } catch (GenericEntityException e) {
		Debug.logError(e, e.getMessage(), module);
		return ServiceUtil.returnError(
			UtilProperties.getMessage(resource, "getPerms.error", new Object[] { e.getMessage() }, locale));
	    }
	}
	result.put("permsList", permsList);
	result.put("perms", perms);
	return result;
    }

    public static Map<String, Object> setLogout(DispatchContext dctx, Map<String, ? extends Object> context) {
	Locale locale = (Locale) context.get("locale");
	Map<String, Object> result = ServiceUtil.returnSuccess();
	Delegator delegator = dctx.getDelegator();

	String sessionKey = (String) context.get("sessionKey");
	if (UtilValidate.isNotEmpty(sessionKey)) {
	    try {
		GenericValue userLoginToken = delegator.findOne("UserLoginToken",
			UtilMisc.toMap("sessionKey", sessionKey), false);
		delegator.removeValue(userLoginToken);
	    } catch (GenericEntityException e) {
		Debug.logError(e, e.getMessage(), module);
		return ServiceUtil.returnError(UtilProperties.getMessage(resource, "setLogout.error",
			new Object[] { e.getMessage() }, locale));
	    }
	}

	return result;
    }
    
    // 验证码干扰线数
//  private static int lineCount = 10;
  static Random random = new Random();

  // 生成验证码,返回base64 图片格式
  public static Map<String, Object> randomImage(DispatchContext ctx, Map<String, ? extends Object> context) {
	Debug.log("randomImage   === start");
	Delegator delegator = ctx.getDelegator();
	Map<String, Object> result = ServiceUtil.returnSuccess();
	String captchaSizeConfig = UtilProperties.getPropertyValue("captcha.properties", "captcha.default");
	String[] captchaSizeConfigs = captchaSizeConfig.split("\\|");
	try {
	    int fontSize = Integer.parseInt(captchaSizeConfigs[0]);
	    double comformnum = 1.5D;
	    int fontSizes = (int) (fontSize * comformnum);
	    int height = Integer.parseInt(captchaSizeConfigs[1]);
	    int width = Integer.parseInt(captchaSizeConfigs[2]);
	    int charsToPrint = UtilProperties.getPropertyAsInteger("captcha.properties", "captcha.code_length", 6)
		    .intValue();
	    char[] availableChars = UtilProperties.getPropertyValue("captcha.properties", "captcha.characters")
		    .toCharArray();
//	    Color backgroundColor = Color.gray;
	    Color borderColor = Color.DARK_GRAY;
	    Color textColor = Color.BLACK;
	    Color circleColor = new Color(160, 160, 160);
	    Font textFont = new Font("Arial", 0, fontSizes);
	    int circlesToDraw = 6;
	    float horizMargin = 20.0F;
	    double rotationRange = 0.7D;
	    BufferedImage bufferedImage = new BufferedImage(width, height, 1);
	    Graphics2D g = (Graphics2D) bufferedImage.getGraphics();

	    // 设置背景色
	    // g.setColor(backgroundColor);
	    // g.setColor(getRandColor(200, 250));
	    g.setColor(Color.WHITE);
	    g.fillRect(0, 0, width, height);

	    g.setColor(circleColor);

//	    // 设置干扰线
//	    for (int i = 0; i < lineCount; i++) {
//	        int xs = random.nextInt(width);
//	        int ys = random.nextInt(height);
//	        int xe = xs + random.nextInt(width);
//	        int ye = ys + random.nextInt(height);
//	        g.setColor(getRandColor(1, 255));
//	        g.drawLine(xs, ys, xe, ye);
//	    }
	    // 添加噪点
//	    float yawpRate = 0.01f;// 噪声率
//	    int area = (int) (yawpRate * width * height);
//	    area = area * 50;
//	    for (int i = 0; i < area; i++) {
//	        int x = random.nextInt(width);
//	        int y = random.nextInt(height);
//	        bufferedImage.setRGB(x, y, random.nextInt(255));
//	    }

	    // 放验证码
	    for (int i = 0; i < circlesToDraw; i++) {
		int circleRadius = (int) (Math.random() * height / 2.0D);
		int circleX = (int) (Math.random() * width - circleRadius);
		int circleY = (int) (Math.random() * height - circleRadius);
		g.drawOval(circleX, circleY, circleRadius * 2, circleRadius * 2);
	    }

	    // 设置字体
	    // g.setColor(textColor);
	    g.setFont(textFont);

	    FontMetrics fontMetrics = g.getFontMetrics();
	    int maxAdvance = fontMetrics.getMaxAdvance();
	    int fontHeight = fontMetrics.getHeight();

	    String captchaCode = RandomStringUtils.random(charsToPrint, availableChars);

	    float spaceForLetters = -horizMargin * 2.0F + width;
	    float spacePerChar = spaceForLetters / (charsToPrint - 1.0F);

	    // 放置验证码
	    for (int i = 0; i < captchaCode.length(); i++) {
		int charWidth = fontMetrics.charWidth(captchaCode.charAt(i));
		int charDim = Math.max(maxAdvance, fontHeight);
		int halfCharDim = charDim / 2;

		BufferedImage charImage = new BufferedImage(charDim, charDim, 2);
		Graphics2D charGraphics = charImage.createGraphics();
		charGraphics.translate(halfCharDim, halfCharDim);
		double angle = (Math.random() - 0.5D) * rotationRange;
		charGraphics.transform(AffineTransform.getRotateInstance(angle));
		charGraphics.translate(-halfCharDim, -halfCharDim);
		charGraphics.setColor(textColor);
		charGraphics.setFont(textFont);

		int charX = (int) (0.5D * charDim - 0.5D * charWidth);
		charGraphics.drawString("" + captchaCode.charAt(i), charX,
			(charDim - fontMetrics.getAscent()) / 2 + fontMetrics.getAscent());

		float x = horizMargin + spacePerChar * i - charDim / 2.0F;
		int y = (height - charDim) / 2;

		g.drawImage(charImage, (int) x, y, charDim, charDim, null, null);

		charGraphics.dispose();
	    }

	    // 画边框
	    g.setColor(borderColor);
	    g.drawRect(0, 0, width - 1, height - 1);
	    // 图象生效
	    g.dispose();

	    ByteArrayOutputStream baos = new ByteArrayOutputStream();// io流
	    ImageIO.write(bufferedImage, "png", baos);// 写入流中
	    byte[] bytes = baos.toByteArray();// 转换成字节
	    BASE64Encoder encoder = new BASE64Encoder();
	    String png_base64 = encoder.encodeBuffer(bytes).trim();// 转换成base64串
	    png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");// 删除 \r\n
	    result.put("nfs", "data:image/jpg;base64," + png_base64);
	    GenericValue codeEntity = delegator.makeValue("AutoCaptchaCode");
	    String checkKey = (String) context.get("checkKey");
	    codeEntity.set("checkKey", checkKey);
	    codeEntity.set("code", captchaCode);
	    codeEntity.create();
	} catch (NumberFormatException e) {
	    e.printStackTrace();
	} catch (IOException e) {
	    e.printStackTrace();
	} catch (GenericEntityException e) {
	    e.printStackTrace();
	}
	Debug.log("randomImage   === end");
	return result;
  }

//得到随机颜色
  private static Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色
	if (fc > 255)
	    fc = 255;
	if (bc > 255)
	    bc = 255;
	int r = fc + random.nextInt(bc - fc);
	int g = fc + random.nextInt(bc - fc);
	int b = fc + random.nextInt(bc - fc);
	return new Color(r, g, b);
  }

  

	// 生成验证码
	public static Map<String, Object> sentSms(DispatchContext ctx, Map<String, ? extends Object> context) {
		Debug.log("sentSms   === start");
		Delegator delegator = ctx.getDelegator();
		Map<String, Object> result = ServiceUtil.returnSuccess();

		try {

			int charsToPrint = UtilProperties.getPropertyAsInteger("captcha.properties", "captcha.code_length", 6)
					.intValue();
			char[] availableChars = UtilProperties.getPropertyValue("captcha.properties", "captcha.characters")
					.toCharArray();

			String captchaCode = RandomStringUtils.random(charsToPrint, availableChars);

			// 调用sms 发送短信
			// TODO

			GenericValue codeEntity = delegator.makeValue("AutoCaptchaCode");
			String mobile = (String) context.get("mobile");
			codeEntity.set("checkKey", mobile);
			codeEntity.set("code", captchaCode);
			codeEntity.create();
		} catch (NumberFormatException e) {
			Debug.logError(e, e.getMessage(), module);

		} catch (GenericEntityException e) {
			Debug.logError(e, e.getMessage(), module);
		}
		Debug.log("sentSms   === end");
		return result;
	}

}
